package com.bestcem.xm.user.controller;

import cn.hutool.core.lang.ObjectId;
import com.alibaba.fastjson.JSONObject;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.domain.web.XmResultJson;
import com.bestcem.xm.common.core.enums.ReqErrorCodeEnum;
import com.bestcem.xm.common.core.enums.ResourceErrorCodeEnum;
import com.bestcem.xm.common.core.uitls.EmailUtil;
import com.bestcem.xm.component.security.annotation.XmAuth;
import com.bestcem.xm.component.security.context.SecurityContextHolder;
import com.bestcem.xm.component.security.dto.TokenDTO;
import com.bestcem.xm.user.config.properties.UserEmailProperties;
import com.bestcem.xm.user.constant.CommonConstant;
import com.bestcem.xm.user.constant.MailConstant;
import com.bestcem.xm.user.controller.vo.user.PageSmtpResponseVO;
import com.bestcem.xm.user.controller.vo.user.UserSmtpVO;
import com.bestcem.xm.user.controller.vo.user.request.*;
import com.bestcem.xm.user.enums.SmtpValidateStatusEnum;
import com.bestcem.xm.user.enums.UserEnum;
import com.bestcem.xm.user.enums.UserSmtpValidateStatusEnum;
import com.bestcem.xm.user.service.MailService;
import com.bestcem.xm.user.service.UserSmtpService;
import com.bestcem.xm.user.service.dto.PageRequestDTO;
import com.bestcem.xm.user.service.dto.PageResponseDTO;
import com.bestcem.xm.user.service.dto.user.UserSmtpDTO;
import com.bestcem.xm.user.util.business.DataBaseUtil;
import com.bestcem.xm.user.util.convert.UserSmtpConvert;
import com.bestcem.xm.user.util.converter.UserSmtpConverter;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.Properties;

/**
 * 邮箱配置相关服务
 *
 * @author qiongyu.cui <qiongyu.cui@idiaoyan.com>
 * @version v1.0
 * @date 2022/3/16 11:34
 */
@Slf4j
@RestController
@RequestMapping(value = "/user/smtps")
public class UserSmtpController {

    @Resource
    private UserSmtpService userSmtpService;

    @Resource
    private MailService mailService;

    @Resource
    private UserEmailProperties userEmailProperties;

    @Resource
    private UserSmtpConvert userSmtpConvert;

    /**
     * 分页查询邮箱配置信息
     * 获取邮箱设置：当url指定id时，直接查询该id的邮箱设置，忽略其他筛选参数
     * 当url没有指定id时，返回分页查询结果，参数在query中
     * <p>
     * python引用：apps.user.model_handlers.SmtpHandler.get
     * * - “@decorators.render_json“
     * * - ”@decorators.permission”
     *
     * @param requestVO 分页请求信息
     * @return com.bestcem.xm.util.XmResultJson<com.bestcem.xm.user.controller.vo.user.PageSmtpResponseVO>
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/03/18 14:15
     */
    @GetMapping("/")
    public XmResultJson<Object> smtp(@Valid UserSmtpPageRequestVO requestVO) {
        // 获取当前的登录信息
        String orgId = SecurityContextHolder.getOrgId();
        //兼容老版本
        if (Objects.isNull(requestVO.getPage()) && Objects.isNull(requestVO.getRowsPerPage())) {
            List<Integer> validateStatus = Lists.newArrayList(SmtpValidateStatusEnum.VERIFYSUCCESS.getIndex());
            ServiceResult<List<UserSmtpDTO>> listResult = userSmtpService.listSmtp(orgId, requestVO.getDescending(), "", validateStatus);
            if (listResult.isSuccess()) {
                List<UserSmtpDTO> result = listResult.getData();
                return XmResultJson.success(UserSmtpConverter.userSmtpDtosToVos(result));
            }
            return XmResultJson.fail(listResult.getErrorData(), listResult.getMsg());
        } else {
            PageRequestDTO pageDTO = new PageRequestDTO();
            pageDTO.setPage(Objects.isNull(requestVO.getPage()) ? 1 : requestVO.getPage());
            pageDTO.setSize(Objects.isNull(requestVO.getRowsPerPage()) ? 10 : requestVO.getRowsPerPage());
            pageDTO.setDescending(requestVO.getDescending());
            pageDTO.setSortBy(requestVO.getSortBy());

            List<Integer> validateStatus = Lists.newArrayList(SmtpValidateStatusEnum.UNVERIFIED.getIndex(),
                    SmtpValidateStatusEnum.VERIFYSUCCESS.getIndex());
            ServiceResult<PageResponseDTO<UserSmtpDTO>> pageResult = userSmtpService.listByPage(pageDTO, orgId, validateStatus);
            if (pageResult.isSuccess()) {
                PageSmtpResponseVO responseVO = new PageSmtpResponseVO();
                PageResponseDTO<UserSmtpDTO> result = pageResult.getData();
                responseVO.setRows(UserSmtpConverter.userSmtpDtosToVos(result.getRows()));
                responseVO.setTotalCount(result.getTotal());
                responseVO.setPage(pageDTO.getPage());
                return XmResultJson.success(responseVO);
            }
            return XmResultJson.fail(pageResult.getErrorData(), pageResult.getMsg());
        }

    }

    /**
     * 查询邮箱配置列表信息
     * 获取邮箱设置：当url指定id时，直接查询该id的邮箱设置，忽略其他筛选参数
     * 当url没有指定id时，返回分页查询结果，参数在query中
     * <p>
     * python引用：apps.user.model_handlers.SmtpHandler.get
     * * - “@decorators.render_json“
     * * - ”@decorators.permission”
     *
     * @param requestVO 列表请求信息
     * @return com.bestcem.xm.util.XmResultJson<java.util.List < com.bestcem.xm.user.controller.vo.user.UserSmtpVO>>
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/05/29 13:57
     */
    @GetMapping("/list/")
    public XmResultJson<List<UserSmtpVO>> listSmtp(UserSmtpListRequestVO requestVO) {
        // 获取当前的登录信息
        TokenDTO currentToken = SecurityContextHolder.getToken();

        String orgId = currentToken.getOrgId();
        List<Integer> validateStatus = Lists.newArrayList(SmtpValidateStatusEnum.UNVERIFIED.getIndex(),
                SmtpValidateStatusEnum.VERIFYSUCCESS.getIndex());
        ServiceResult<List<UserSmtpDTO>> listResult = userSmtpService.listSmtp(orgId, requestVO.getDescending(), requestVO.getSortBy(), validateStatus);
        if (listResult.isSuccess()) {
            List<UserSmtpDTO> result = listResult.getData();
            return XmResultJson.success(UserSmtpConverter.userSmtpDtosToVos(result));
        }
        return XmResultJson.fail(listResult.getErrorData(), listResult.getMsg());
    }

    /**
     * 验证邮箱设置
     * 邮箱服务器可用性验证
     *
     * @param vo 入参
     * @return com.bestcem.xm.util.XmResultJson<java.lang.Boolean>
     * @author panyun <yun.pan@idiaoyan.com>
     * @date 2022/3/17 11:59
     */
    @PostMapping("/validate/")
    @XmAuth
    public XmResultJson<JSONObject> smtpValidate(@RequestBody SmtpValidateRequestVO vo) {
        if (StringUtils.isBlank(vo.getAccount()) || StringUtils.isBlank(vo.getPassword())
                || StringUtils.isBlank(vo.getHost()) || StringUtils.isBlank(vo.getPort().toString())) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_LOST, "参数缺失");
        }
        if (Boolean.FALSE.equals(EmailUtil.validateEmail(vo.getAccount()))) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_FORMAT, "邮箱格式错误");
        }

        JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
        javaMailSender.setProtocol(userEmailProperties.getSmtpProtocol());
        javaMailSender.setHost(vo.getHost());
        javaMailSender.setUsername(vo.getAccount());
        javaMailSender.setPassword(vo.getPassword());
        javaMailSender.setDefaultEncoding(userEmailProperties.getSmtpEncoding());
        Properties properties = new Properties();
        // 设置超时时间
        properties.setProperty(CommonConstant.MAIL_SMTP_TIMEOUT, userEmailProperties.getSmtpTimeout());

        // 如果是ssl的话,需要设置以下属性
        if (Objects.nonNull(vo.getSslFlag()) && vo.getSslFlag().equals(Boolean.TRUE)) {
            properties.setProperty(CommonConstant.MAIL_SMTP_AUTH, userEmailProperties.getSmtpAuth());
            properties.setProperty(CommonConstant.MAIL_SMTP_SOCKETFACTORY_CLASS,
                    userEmailProperties.getSmtpSocketFactoryClass());
            properties.setProperty(CommonConstant.MAIL_SMTP_SOCKETFACTORY_PORT,
                    String.valueOf(userEmailProperties.getDefaultPort()));
        }
        javaMailSender.setJavaMailProperties(properties);

        String subject = "邮箱服务器可用性";
        boolean send = mailService.sendEmail(javaMailSender, vo.getAccount(), new String[]{MailConstant.VALIDATE_EMAIL_STATUS_MAIL_TO}, subject, "", new HashMap<>());
        if (!send) {
            return XmResultJson.fail(ReqErrorCodeEnum.EMAIL_SERVER_DISABLED, "邮箱服务器验证未通过");
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("status", Boolean.TRUE);
        return XmResultJson.success(jsonObject);

    }

    /**
     * 添加邮箱设置
     * 创建邮箱
     *
     * @param vo 入参
     * @return com.bestcem.xm.util.XmResultJson<java.lang.String>
     * @author panyun <yun.pan@idiaoyan.com>
     * @date 2022/3/17 11:59
     */
    @PostMapping("/")
    public XmResultJson<HashMap<String, String>> createSmtp(@Valid @RequestBody UserSmtpCreateVO vo) {
        TokenDTO currentToken = SecurityContextHolder.getToken();
        if (StringUtils.isNotBlank(vo.getAccount())) {
            UserSmtpDTO smtpDTO = new UserSmtpDTO();
            smtpDTO.setOrgId(currentToken.getOrgId());
            smtpDTO.setAccount(vo.getAccount());
            ServiceResult<List<UserSmtpDTO>> listServiceResult = userSmtpService.selectBySelective(smtpDTO);
            if (listServiceResult.isSuccess() && CollectionUtils.isNotEmpty(listServiceResult.getData())) {
                return XmResultJson.fail(ReqErrorCodeEnum.PARAM_RANGE, "邮箱账户已存在");
            }
        }
        if (!UserSmtpValidateStatusEnum.VERIFIED_SUCCESS.getStatus().equals(vo.getValidateStatus())) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_RANGE, "邮箱服务器验证未通过");
        }
        if (Boolean.TRUE.equals(vo.getIsSystem())) {
            return XmResultJson.fail(ResourceErrorCodeEnum.FORBIDDEN, "当前禁止创建系统邮箱");
        }

        UserSmtpDTO userSmtpDTO = new UserSmtpDTO();
        userSmtpDTO.setSmtpId(DataBaseUtil.generateId())
                .setAccount(vo.getAccount())
                .setDescription(vo.getDescription())
                .setHost(vo.getHost())
                .setSslFlag(Boolean.TRUE.equals(vo.getIsSSL()) ? UserEnum.USER_YES.getFlag() : UserEnum.USER_NO.getFlag())
                .setPassword(vo.getPassword())
                .setPort(Integer.parseInt(vo.getPort()))
                .setValidateStatus(vo.getValidateStatus())
                .setDeliverFlag(Boolean.TRUE.equals(vo.getIsDeliver()) ? UserEnum.USER_YES.getFlag() : UserEnum.USER_NO.getFlag())
                .setNoticeFlag(Boolean.TRUE.equals(vo.getIsNotice()) ? UserEnum.USER_YES.getFlag() : UserEnum.USER_NO.getFlag())
                .setSystemFlag(Boolean.TRUE.equals(vo.getIsSystem()) ? UserEnum.USER_YES.getFlag() : UserEnum.USER_NO.getFlag())
                .setOrgId(currentToken.getOrgId());
        ServiceResult<String> result = userSmtpService.createSmtp(currentToken.getOrgId(), userSmtpDTO);
        if (result.isSuccess()) {
            HashMap<String, String> map = new HashMap<>(16);
            map.put("id", result.getData());
            return XmResultJson.success(map);
        }
        return XmResultJson.fail(result.getErrorData(), result.getMsg());
    }

    /**
     * 根据id获取邮箱设置
     *
     * @param id smtpId
     * @return com.bestcem.xm.util.XmResultJson<com.bestcem.xm.user.service.dto.user.UserSmtpDTO>
     * @author panyun <yun.pan@idiaoyan.com>
     * @date 2022/3/17 22:55
     */
    @GetMapping("/{id}")
    public XmResultJson<UserSmtpDTO> getById(@PathVariable("id") String id) {
        if (!ObjectId.isValid(id)) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_FORMAT, "id格式不正确");
        }
        ServiceResult<UserSmtpDTO> result = userSmtpService.selectById(id);
        return XmResultJson.success(result.getData());
    }

    /**
     * 更新邮箱设置
     *
     * @param id 邮箱配置id
     * @param vo 接口入参
     * @return com.bestcem.xm.util.XmResultJson<java.lang.Object>
     * @author panyun <yun.pan@idiaoyan.com>
     * @date 2022/3/17 18:21
     */
    @PutMapping("/{id}")
    public XmResultJson<HashMap<String, String>> updateSmtp(@PathVariable("id") String id, @RequestBody UserSmtpUpdateVO vo) {
        if (StringUtils.isBlank(id)) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_LOST, "url must endswith id");
        }
        if (!ObjectId.isValid(id)) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_FORMAT, "smtpId格式不正确");
        }
        vo.setSmtpId(id);
        TokenDTO currentToken = SecurityContextHolder.getToken();
        ServiceResult<String> result = userSmtpService.updateSmtp(currentToken.getOrgId(), userSmtpConvert.updateVoToDto(vo));
        if (result.isSuccess()) {
            HashMap<String, String> map = new HashMap<>(16);
            map.put("id", result.getData());
            return XmResultJson.success(map);
        }
        return XmResultJson.fail(result.getErrorData(), result.getMsg());
    }

    /**
     * 删除邮箱设置
     *
     * @param id 邮箱id
     * @return com.bestcem.xm.util.XmResultJson<java.lang.Object>
     * @author panyun <yun.pan@idiaoyan.com>
     * @date 2022/3/17 18:29
     */
    @DeleteMapping("/{id}")
    public XmResultJson<HashMap<String, Integer>> deleteSmtp(@PathVariable("id") String id) {
        if (!ObjectId.isValid(id)) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_FORMAT, "smtpId格式不正确");
        }
        TokenDTO currentToken = SecurityContextHolder.getToken();
        ServiceResult<UserSmtpDTO> selectById = userSmtpService.selectById(id);
        if (Objects.isNull(selectById.getData())) {
            return XmResultJson.fail(ResourceErrorCodeEnum.NOT_FOUND, "Smtp[id=" + id + "] not found");
        }

        ServiceResult<Integer> result = userSmtpService.deleteSmtpByIds(currentToken.getOrgId(), Lists.newArrayList(id));
        if (result.isSuccess()) {
            HashMap<String, Integer> map = new HashMap<>(16);
            map.put("deletedCount", result.getData());
            return XmResultJson.success(map);
        }
        return XmResultJson.fail(result.getErrorData(), result.getMsg());
    }

    /**
     * 批量删除邮箱设置
     *
     * @param ids id列表
     * @return com.bestcem.xm.util.XmResultJson<java.lang.Object>
     * @author panyun <yun.pan@idiaoyan.com>
     * @date 2022/3/17 18:29
     */
    @DeleteMapping("/")
    public XmResultJson<HashMap<String, Integer>> deleteSmtp(@RequestParam(value = "idList") List<String> ids) {
        TokenDTO currentToken = SecurityContextHolder.getToken();
        if (CollectionUtils.isEmpty(ids)) {
            return XmResultJson.fail(ReqErrorCodeEnum.PARAM_LOST, "idList is required");
        }

        ServiceResult<Integer> result = userSmtpService.deleteSmtpByIds(currentToken.getOrgId(), ids);
        if (result.isSuccess()) {
            HashMap<String, Integer> map = new HashMap<>(16);
            map.put("deletedCount", result.getData());
            return XmResultJson.success(map);
        }
        return XmResultJson.fail(result.getErrorData(), result.getMsg());
    }


}
